home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 317 / asmsrc / subsegs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-20  |  9.0 KB  |  295 lines

  1. /* subsegs.c - subsegments - */
  2.   
  3. /* Copyright (C) 1987 Free Software Foundation, Inc.
  4.  
  5. This file is part of Gas, the GNU Assembler.
  6.  
  7. The GNU assembler is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Assembler General
  12. Public License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. the GNU Assembler, but only under the conditions described in the
  16. GNU Assembler General Public License.  A copy of this license is
  17. supposed to have been given to you along with the GNU Assembler
  18. so you can know your rights and responsibilities.  It should be
  19. in a file named COPYING.  Among other things, the copyright
  20. notice and this notice must be preserved on all copies.  */
  21.  
  22. /*
  23.  * Segments & sub-segments.
  24.  */
  25.  
  26. #include "as.h"
  27. #include "subsegs.h"
  28. #include "obstack.h"
  29. #include "frags.h"
  30. #include "struc-symbol.h"
  31. #include "write.h"
  32.  
  33. frchainS*    frchain_root,
  34.     *    frchain_now,    /* Commented in "subsegs.h". */
  35.     *    data0_frchainP;
  36.  
  37.  
  38. int                /* in: segT   out: N_TYPE bits */
  39. seg_N_TYPE[] = {
  40.   N_ABS,
  41.   N_TEXT,
  42.   N_DATA,
  43.   N_BSS,
  44.   N_UNDF,
  45.   N_UNDF,
  46.   N_UNDF,
  47.   N_UNDF,
  48.   N_UNDF,
  49.   N_UNDF
  50. };
  51.  
  52.  
  53. char *                /* in: segT   out: char* */
  54. seg_name[] = {
  55.   "absolute",
  56.   "text",
  57.   "data",
  58.   "bss",
  59.   "unknown",
  60.   "absent",
  61.   "pass1",
  62.   "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
  63.   "bignum/flonum",
  64.   "difference",
  65.   ""
  66.   };                /* Used by error reporters, dumpers etc. */
  67.  
  68. segT N_TYPE_seg [N_TYPE+2] =    /* N_TYPE == 0x1E = 32-2 */
  69. {
  70.   SEG_UNKNOWN,            /* N_UNDF == 0 */
  71.   SEG_GOOF,
  72.   SEG_ABSOLUTE,            /* N_ABS == 2 */
  73.   SEG_GOOF,
  74.   SEG_TEXT,            /* N_TEXT == 4 */
  75.   SEG_GOOF,
  76.   SEG_DATA,            /* N_DATA == 6 */
  77.   SEG_GOOF,
  78.   SEG_BSS,            /* N_BSS == 8 */
  79.   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  80.   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  81.   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF
  82. };
  83.  
  84. void
  85. subsegs_begin()
  86. {
  87.   /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
  88.   know( SEG_ABSOLUTE    ==0 );
  89.   know( SEG_TEXT        ==1 );
  90.   know( SEG_DATA        ==2 );
  91.   know( SEG_BSS         ==3 );
  92.   know( SEG_UNKNOWN     ==4 );
  93.   know( SEG_NONE        ==5 );
  94.   know( SEG_PASS1    ==6 );
  95.   know( SEG_GOOF    ==7 );
  96.   know( SEG_BIG        ==8 );
  97.   know( SEG_DIFFERENCE    ==9 );
  98.   know( SEG_MAXIMUM_ORDINAL == SEG_DIFFERENCE );
  99.   know( seg_name [(int) SEG_MAXIMUM_ORDINAL + 1] [0] == 0 );
  100.  
  101.   obstack_begin( &frags, 5000);
  102.   frchain_root = NULL;
  103.   frchain_now  = NULL;        /* Warn new_subseg() that we are booting. */
  104.                 /* Fake up 1st frag. */
  105.                 /* It won't be used=> is ok if obstack... */
  106.                 /* pads the end of it for alignment. */
  107.   frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
  108.   /* obstack_1blank( &frags, SIZEOF_STRUCT_FRAG, & frag_now ); */
  109.                 /* This 1st frag will not be in any frchain. */
  110.                 /* We simply give subseg_new somewhere to scribble. */
  111.   now_subseg = 42;        /* Lie for 1st call to subseg_new. */
  112.   subseg_new (SEG_DATA, 0);    /* .data 0 */
  113.   data0_frchainP = frchain_now;
  114. }
  115.  
  116. /*
  117.  *            subseg_change()
  118.  *
  119.  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
  120.  * subsegment. If we are already in the correct subsegment, change nothing.
  121.  * This is used eg as a worker for subseg_new [which does make a new frag_now]
  122.  * and for changing segments after we have read the source. We construct eg
  123.  * fixSs even after the source file is read, so we do have to keep the
  124.  * segment context correct.
  125.  */
  126. void
  127. subseg_change (seg, subseg)
  128.      register segT    seg;
  129.      register int    subseg;
  130. {
  131.   now_seg     = seg;
  132.   now_subseg = subseg;
  133.   if (seg == SEG_DATA)
  134.     {
  135.       seg_fix_rootP = & data_fix_root;
  136.     }
  137.   else
  138.     {
  139.       know (seg == SEG_TEXT);
  140.       seg_fix_rootP = & text_fix_root;
  141.     }
  142. }
  143.  
  144. /*
  145.  *            subseg_new()
  146.  *
  147.  * If you attempt to change to the current subsegment, nothing happens.
  148.  *
  149.  * In:    segT, subsegT code for new subsegment.
  150.  *    frag_now -> incomplete frag for current subsegment.
  151.  *    If frag_now==NULL, then there is no old, incomplete frag, so
  152.  *    the old frag is not closed off.
  153.  *
  154.  * Out:    now_subseg, now_seg updated.
  155.  *    Frchain_now points to the (possibly new) struct frchain for this
  156.  *    sub-segment.
  157.  *    Frchain_root updated if needed.
  158.  */
  159.  
  160. void
  161. subseg_new (seg, subseg)    /* begin assembly for a new sub-segment */
  162.      register segT    seg;    /* SEG_DATA or SEG_TEXT */
  163.      register subsegT    subseg;
  164. {
  165.   long tmp;        /* JF for obstack alignment hacking */
  166.  
  167.   know( seg == SEG_DATA || seg == SEG_TEXT );
  168.  
  169.   if (seg != now_seg || subseg != now_subseg)
  170.     {                /* we just changed sub-segments */
  171.       register    frchainS *    frcP;    /* crawl frchain chain */
  172.       register    frchainS**    lastPP;    /* address of last pointer */
  173.         frchainS *    newP;    /* address of new frchain */
  174.       register fragS *        former_last_fragP;
  175.       register fragS *        new_fragP;
  176.  
  177.       if (frag_now)        /* If not bootstrapping. */
  178.     {
  179.       frag_now -> fr_fix = obstack_next_free(& frags) - frag_now -> fr_literal;
  180.       frag_wane(frag_now);    /* Close off any frag in old subseg. */
  181.     }
  182. /*
  183.  * It would be nice to keep an obstack for each subsegment, if we swap
  184.  * subsegments a lot. Hence we would have much fewer frag_wanes().
  185.  */
  186.       {
  187.  
  188.     obstack_finish( &frags);
  189.     /*
  190.      * If we don't do the above, the next object we put on obstack frags
  191.      * will appear to start at the fr_literal of the current frag.
  192.      * Also, above ensures that the next object will begin on a
  193.      * address that is aligned correctly for the engine that runs
  194.      * this program.
  195.      */
  196.       }
  197.       subseg_change (seg, (int)subseg);
  198.       /*
  199.        * Attempt to find or make a frchain for that sub seg.
  200.        * Crawl along chain of frchainSs, begins @ frchain_root.
  201.        * If we need to make a frchainS, link it into correct
  202.        * position of chain rooted in frchain_root.
  203.        */
  204.       for (frcP = * (lastPP = & frchain_root);
  205.        frcP
  206.        && (int)(frcP -> frch_seg) <= (int)seg;
  207.        frcP = * ( lastPP = & frcP -> frch_next)
  208.       )
  209.     {
  210.       if (   (int)(frcP -> frch_seg) == (int)seg
  211.           && frcP -> frch_subseg >= subseg)
  212.         {
  213.           break;
  214.         }
  215.     }
  216.       /*
  217.        * frcP:        Address of the 1st frchainS in correct segment with
  218.        *        frch_subseg >= subseg.
  219.        *        We want to either use this frchainS, or we want
  220.        *        to insert a new frchainS just before it.
  221.        *
  222.        *        If frcP==NULL, then we are at the end of the chain
  223.        *        of frchainS-s. A NULL frcP means we fell off the end
  224.        *        of the chain looking for a
  225.        *        frch_subseg >= subseg, so we
  226.        *        must make a new frchainS.
  227.        *
  228.        *        If we ever maintain a pointer to
  229.        *        the last frchainS in the chain, we change that pointer
  230.        *        ONLY when frcP==NULL.
  231.        *
  232.        * lastPP:    Address of the pointer with value frcP;
  233.        *        Never NULL.
  234.        *        May point to frchain_root.
  235.        *
  236.        */
  237.       if (   ! frcP
  238.       || (   (int)(frcP -> frch_seg) > (int)seg
  239.           || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
  240.     {
  241.       /*
  242.        * This should be the only code that creates a frchainS.
  243.        */
  244.       newP=(frchainS *)obstack_alloc(&frags,sizeof(frchainS));
  245.       /* obstack_1blank( &frags, sizeof(frchainS), &newP); */
  246.                 /* This begines on a good boundary */
  247.                 /* because a obstack_done() preceeded  it. */
  248.                 /* It implies an obstack_done(), so we */
  249.                 /* expect the next object allocated to */
  250.                 /* begin on a correct boundary. */
  251.       *lastPP = newP;
  252.       newP -> frch_next = frcP; /* perhaps NULL */
  253.       (frcP = newP) -> frch_subseg        = subseg;
  254.           newP  -> frch_seg        = seg;
  255.           newP  -> frch_last         = NULL;
  256.     }
  257.       /*
  258.        * Here with frcP ->ing to the frchainS for subseg.
  259.        */
  260.       frchain_now = frcP;
  261.       /*
  262.        * Make a fresh frag for the subsegment.
  263.        */
  264.                 /* We expect this to happen on a correct */
  265.                 /* boundary since it was proceeded by a */
  266.                 /* obstack_done(). */
  267.       tmp=obstack_alignment_mask(&frags);    /* JF disable alignment */
  268.       obstack_alignment_mask(&frags)=0;
  269.       frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
  270.       obstack_alignment_mask(&frags)=tmp;
  271.       /* know( frags . obstack_c_next_free == frag_now -> fr_literal ); */
  272.                 /* But we want any more chars to come */
  273.                 /* immediately after the structure we just made. */
  274.       new_fragP = frag_now;
  275.       new_fragP -> fr_next = NULL;
  276.       /*
  277.        * Append new frag to current frchain.
  278.        */
  279.       former_last_fragP = frcP -> frch_last;
  280.       if (former_last_fragP)
  281.     {
  282.       know( former_last_fragP -> fr_next == NULL );
  283.       know( frchain_now -> frch_root );
  284.       former_last_fragP -> fr_next = new_fragP;
  285.     }
  286.       else
  287.     {
  288.       frcP -> frch_root = new_fragP;
  289.     }
  290.       frcP -> frch_last = new_fragP;
  291.     }                /* if (changing subsegments) */
  292. }                /* subseg_new() */
  293.  
  294. /* end: subsegs.c */
  295.